package jp.reflexworks.gae.blogger;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.logging.Logger;

public class Blogger {
	
	Logger logger = Logger.getLogger(this.getClass().getName());
	
//singleton
//	private static final Blogger instance = new Blogger();
//	private Blogger() {
//	}
//	public static Blogger getInstance() {
//		return Blogger.instance;
//	}
	
	private static final String USER_AGENT = "Blogger.java";
	private static final String GDATA_VERSION = "2";
	
	public static final int TYPE_AUTHORIZATION_AUTH_SUB = 1;
	public static final int TYPE_AUTHORIZATION_CLIENT_LOGIN = 2;
	public static final String TYPE_NAME_AUTHORIZATION_AUTH_SUB = "AuthSub";
	public static final String TYPE_NAME_AUTHORIZATION_CLIENT_LOGIN = "ClientLogin";
	
	//AuthSub用
	//vtecadmin
//	private static final String AUTH_SUB_BLOG_ID = "7726217364309932343";
//	private static final String AUTH_SUB_PROFILE_ID = "07431124518582514230";
	//vtecdemo
	private String blogId = null;
	//private static final String AUTH_SUB_PROFILE_ID = "11047747929288976014";
	private static final String URL_AUTH_SUBSESSION_TOKEN = "https://www.google.com/accounts/AuthSubSessionToken";
	private static final String AUTHORIZATION_HEADER_TYPE_AUTH_SUB = "AuthSub";
	private static final String AUTHORIZATION_HEADER_KEY_AUTH_SUB = "token";
//	private static final String TYPE_AUTHORIZATION_AUTH_SUB = "AuthSub";
	
	
	//clientLogin用
	/*
	 * ClientLogin Request
	 * http://code.google.com/intl/ja/apis/accounts/docs/AuthForInstalledApps.html#Request
	 */
	private static final String URL_CLIENT_LOGIN = "https://www.google.com/accounts/ClientLogin";
//	private static final String CLIENT_LOGIN_EMAIL = "vtecadmin@gmail.com";
//	private static final String CLIENT_LOGIN_PASSWORD = "vtec2009";
	private static final String CLIENT_LOGIN_SERVICE = "blogger";
	private static final String CLIENT_LOGIN_ACCOUNT_TYPE = "GOOGLE";
	private static final String CLIENT_LOGIN_SOURCE = "virtualtechnologyinc-gaeblogger-1";
	private static final String AUTHORIZATION_HEADER_TYPE_CLIENT_LOGIN = "GoogleLogin";
	private static final String AUTHORIZATION_HEADER_KEY_CLIENT_LOGIN = "auth";
	private String queryClientLogin = null;
//	private static final String TYPE_AUTHORIZATION_CLIENT_LOGIN = "ClientLogin";
	
	
	
	private String urlPost = null;

	private String tokenAuth = null;
	private String tokenSession = null;
	private String typeAuthorizationHeader = null;
	private String keyAuthorizationHeader = null;
	private String typeAuthorization = null;
	private String email = null;
	private String password = null;
	
	
	public Blogger(String _blogId){
		blogId = _blogId;
		setAuthType(TYPE_AUTHORIZATION_AUTH_SUB);
	}
	
	
	public Blogger(String _blogId, String _email, String _password){
		blogId = _blogId;
		email = _email;
		password = _password;
		setAuthType(TYPE_AUTHORIZATION_CLIENT_LOGIN);
	}
	
	
	public void setAuthType(int authType) {
		if (authType == TYPE_AUTHORIZATION_AUTH_SUB) {
			typeAuthorizationHeader = AUTHORIZATION_HEADER_TYPE_AUTH_SUB;
			keyAuthorizationHeader = AUTHORIZATION_HEADER_KEY_AUTH_SUB;
			typeAuthorization = TYPE_NAME_AUTHORIZATION_AUTH_SUB;
		} else {
			typeAuthorizationHeader = AUTHORIZATION_HEADER_TYPE_CLIENT_LOGIN;
			keyAuthorizationHeader = AUTHORIZATION_HEADER_KEY_CLIENT_LOGIN;
			typeAuthorization = TYPE_NAME_AUTHORIZATION_CLIENT_LOGIN;
			
			queryClientLogin = createClientLoginPostQuery();
		}
		
		urlPost = "http://www.blogger.com/feeds/" + blogId + "/posts/defaults";
	}


	private String createClientLoginPostQuery() {
		
		Properties props = new Properties();
		props.setProperty("accountType", CLIENT_LOGIN_ACCOUNT_TYPE);
		props.setProperty("Email", email);
		props.setProperty("Passwd", password);
		props.setProperty("service", CLIENT_LOGIN_SERVICE);
		props.setProperty("source", CLIENT_LOGIN_SOURCE);
		
		return createQueryString(props);
	}
		
	private void setHeaderAuthorization(HttpURLConnection conn, String token) {
		conn.setRequestProperty("Authorization", typeAuthorizationHeader + " " + keyAuthorizationHeader + "=\"" + token + "\"");
	}
	
	
	public String clientLogin() {
		log("clientLogin() :blogId=" + blogId + "/urlPost=" + urlPost);
		
		//StringBuilder sb = new StringBuilder();
		String authToken = null;
		
		try {
			URL url = new URL(URL_CLIENT_LOGIN);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setRequestMethod("POST");
			conn.setInstanceFollowRedirects(false);
			conn.setDoOutput(true);
			
			
			conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
			conn.setRequestProperty("User-Agent", USER_AGENT);
			conn.setRequestProperty("GData-Version", GDATA_VERSION);
	
			
			//NOTE UTF-8を渡さないと日本語をPOSTした際に文字化けする
			OutputStreamWriter osw = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
			osw.write(queryClientLogin);
			osw.flush();
			osw.close();		
	
			BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
			
			String line = null;
			
			while ((line = reader.readLine()) != null) {
				//SID, LSID, AuthからAuthだけを返す
				//sb.append(line);
				log(line);
				authToken = parseToken("Auth", line);
				tokenSession = authToken;
			}
			reader.close();
			conn.disconnect();
		} catch (ProtocolException e) {
			log(e.getCause());
		} catch (MalformedURLException e) {
			log(e.getCause());
		} catch (IOException e) {
			log(e.getCause());
		}
		
		return authToken;
	}
	
	
	
	public void setAuthSubSessionToken() {
		
		String authToken = null;
		
		try {
			HttpURLConnection conn = null;
			URL url = new URL(URL_AUTH_SUBSESSION_TOKEN);
			
			conn = (HttpURLConnection) url.openConnection();
			conn.setRequestMethod("GET");
			conn.setInstanceFollowRedirects(false);

			conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
			conn.setRequestProperty("User-Agent", USER_AGENT);
			conn.setRequestProperty("GData-Version", GDATA_VERSION);
			setHeaderAuthorization(conn, tokenAuth);

			conn.connect();

			BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));

			String line = null;
			while ((line = reader.readLine()) != null) {
				log(line);
				authToken = parseToken("Token", line);
				tokenSession = authToken;
			}
			
			reader.close();
			conn.disconnect();
		} catch (ProtocolException e) {
			log(e.getCause());
		} catch (MalformedURLException e) {
			log(e.getCause());
		} catch (IOException e) {
			log(e.getCause());
		}
		
	}


	
	public String post(String atom) {
		
		log("token :" + tokenAuth + " / " + tokenSession);
		StringBuilder sb = new StringBuilder();
		
		try {
			URL url = new URL(urlPost);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setRequestMethod("POST");
			conn.setInstanceFollowRedirects(false);
			conn.setDoOutput(true);
			
			
			conn.setRequestProperty("Content-Type", "application/atom+xml");
			conn.setRequestProperty("User-Agent", USER_AGENT);
			conn.setRequestProperty("Content-Length", Integer.toString(atom.length()));
			setHeaderAuthorization(conn, tokenSession);
			conn.setRequestProperty("GData-Version", GDATA_VERSION);
			
			//conn.connect();
	
			//NOTE UTF-8を渡さないと日本語をPOSTした際に文字化けする
			OutputStreamWriter osw = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
			osw.write(atom);
			osw.flush();
			osw.close();		
	
			BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
			
			String line = null;
			while ((line = reader.readLine()) != null) {
				sb.append(line);
				log(line);
			}
			reader.close();
			conn.disconnect();
		} catch (ProtocolException e) {
			log(e.getCause());
		} catch (MalformedURLException e) {
			log(e.getCause());
		} catch (IOException e) {
			log(e.getCause());
		}
		
		return sb.toString();
	}
	
	/**
	 * Propertiesをkey1=val1&key2=val2...形式の文字列に変換する
	 * 
	 * @param props
	 * @return
	 */
	public String createQueryString(Properties props) {

		List<String> list = new ArrayList<String>();
		for (String key: props.stringPropertyNames()) {
			
			if (props.get(key) == null) {
				list.add(key + "=");
			} else {
				list.add(key + "=" + props.get(key));
			}
		}

		return join(list, "&");
	}
	
	public static String join(List<String> list, String delimiter) {
		
		int len = list.size();
		
		StringBuilder sb = new StringBuilder();
		
		for (int i = 0; i < len; i++) {
			if (i == (len - 1)) {
				sb.append(list.get(i));
			} else {
				sb.append(list.get(i) + delimiter);
			}
		}
		return sb.toString();
	}

	/**
	 * 
	 * tokenName=tokenValue 形式の文字列からtokenValueを求める
	 * 検索対象文字列はtokenNameで始まっていること
	 * 
	 * @param tokenNeme
	 * @param stringQuery
	 * @return
	 */
	private String parseToken(String tokenNeme, String stringQuery) {
		
		stringQuery = stringQuery.trim();

		//検索対象文字列はtokenNameで始まっていること
		if (stringQuery.indexOf(tokenNeme) == 0) {
			return stringQuery.substring((tokenNeme.length() + 1));
		} else {
			return null;
		}
	}
 	
	
	
	private void log(Object o) {
		logger.severe(o.toString());
		System.out.println(o);
	}

	
	
////	
	
	public String getTokenAuth() {
		return tokenAuth;
	}
	public void setTokenAuth(String tokenAuth) {
		this.tokenAuth = tokenAuth;
	}
	public String getTokenSession() {
		return tokenSession;
	}
	public void setTokenSession(String tokenSession) {
		this.tokenSession = tokenSession;
	}

	public String getBlogId() {
		return blogId;
	}

	public void setBlogId(String blogId) {
		this.blogId = blogId;
	}
	
}
